package xxhttp

import (
	"github.com/bytedance/sonic"
	"github.com/duke-git/lancet/v2/convertor"
	"github.com/duke-git/lancet/v2/netutil"
	"github.com/duke-git/lancet/v2/structs"
	"strings"
)

const (
	fileUploadingKey = "@file:"
)

func BuildParams(contentType string, params interface{}, noUrlEncode ...bool) string {
	if HttpContentTypeJson == contentType {
		if b, err := sonic.Marshal(params); err != nil {
			return ""
		} else {
			return string(b)
		}
	} else if HttpContentTypeUrlEncoded == contentType {
		return urlEncodedParams(params, noUrlEncode...)
	}
	return ""
}

func urlEncodedParams(params interface{}, noUrlEncode ...bool) (encodedParamStr string) {
	// If given string/[]byte, converts and returns it directly as string.
	switch v := params.(type) {
	case string, []byte:
		return convertor.ToString(params)
	case []interface{}:
		if len(v) > 0 {
			params = v[0]
		} else {
			params = nil
		}
	}

	// Else converts it to map and does the url encoding.
	pm, _ := structs.ToMap(params)
	m, urlEncode := pm, true
	if len(m) == 0 {
		return convertor.ToString(params)
	}
	if len(noUrlEncode) == 1 {
		urlEncode = !noUrlEncode[0]
	}
	// If there's file uploading, it ignores the url encoding.
	if urlEncode {
		for k, v := range m {
			if strings.Contains(k, fileUploadingKey) || strings.Contains(convertor.ToString(v), fileUploadingKey) {
				urlEncode = false
				break
			}
		}
	}
	s := ""
	for k, v := range m {
		if len(encodedParamStr) > 0 {
			encodedParamStr += "&"
		}
		s = convertor.ToString(v)
		if urlEncode && len(s) > 6 && strings.Compare(s[0:6], fileUploadingKey) != 0 {
			s, _ = netutil.EncodeUrl(s) //gurl.Encode(s)
		}
		encodedParamStr += k + "=" + s
	}
	return
}
